package com.web.controller;

import com.alibaba.fastjson.JSONObject;
import com.core.model.enumType.ApiResponseStatusCode;
import com.core.shared.TraceUtil;
import com.core.websocket.WebSocket;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.util.WebUtils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Created with IntelliJ IDEA.
 * User: lxf
 * Date: 2017/11/28
 * Time: 11:57
 * To change this template use Editor | File and Code Templates.
 */
public class AbstractController {

    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractController.class);

    protected HttpServletRequest getRequest() {
        return ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
    }

    protected HttpSession getSession() {
        return this.getRequest().getSession();
    }

    protected Map<String, Object> getParameterMap() {
        return getParameterMap(this.getRequest());
    }

    protected Map<String, String> getHeaderMap(HttpServletRequest request) {
        Map<String, String> result = new HashMap<>();
        Enumeration headNames = request.getHeaderNames();
        while (headNames.hasMoreElements()) {
            String name = (String) headNames.nextElement();
            result.put(name, request.getHeader(name));
        }

        return result;
    }

    protected Map<String, Object> getParameterMap(HttpServletRequest request) {
        Map<String, Object> parameterMap = new HashMap<>();
        Set<String> keys = request.getParameterMap().keySet();
        for (String key : keys) {
            if (StringUtils.isEmpty(request.getParameter(key))) {
                continue;
            }
            parameterMap.put(key, request.getParameter(key));
        }
        return parameterMap;
    }

    protected boolean isAjaxRequest(HttpServletRequest request) {
        String requestType = request.getHeader("X-Requested-With");
        return StringUtils.isNotBlank(requestType) && StringUtils.equals(requestType, "XMLHttpRequest");
    }

    protected String getIpAddr() {
        return WebSocket.getIpAddress(getRequest());
    }


    protected void addRootCookie(String key, String val, HttpServletResponse response) {
        Cookie cookie = WebUtils.getCookie(getRequest(), key);
        if (cookie == null) {
            cookie = new Cookie(key, val);
        } else {
            cookie.setValue(val);
        }
        cookie.setPath("/");
        response.addCookie(cookie);
        cookie.setMaxAge(1200);
    }

    /**
     * 拦截所有系统级异常.
     *
     * @param ex       the ex
     * @param request  the request
     * @param response the response
     * @return the object
     */
    @ExceptionHandler(Exception.class)
    public Object handleException(Exception ex, HttpServletRequest request, HttpServletResponse response) {
        String traceId = TraceUtil.getRequestTraceId(request);
        LOGGER.error("request exception: traceid:" + traceId, ex);
        if (isAjaxRequest(request)) {
            JSONObject result = new JSONObject();
            result.put("uuid", traceId);
            result.put("code", ApiResponseStatusCode.FAIL.getCode());
            result.put("msg", ex.getMessage());
            result.put("data", null);
            response.setCharacterEncoding("UTF-8");
            response.setHeader("content-type", "application/json;charset=UTF-8");
            response.setStatus(HttpServletResponse.SC_OK);
            flush(response, result);
            return null;
        } else {
            ModelAndView exceptionView = new ModelAndView("500");
            exceptionView.addObject("uuid", traceId);
            return exceptionView;
        }
    }

    /**
     * Flush.
     *
     * @param response the response
     * @param data     the data
     */
    protected void flush(HttpServletResponse response, Object data) {
        try {
            BufferedOutputStream os = new BufferedOutputStream(response.getOutputStream());
            os.write(JSONObject.toJSONString(data).getBytes("UTF-8"));
            os.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}
